# 将文件保存为：byd_stock_analysis.py

import pandas as pd
import numpy as np
import matplotlib

matplotlib.use('Agg')  # 使用非交互式后端
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import warnings

warnings.filterwarnings('ignore')


def setup_chinese_font():
    """设置中文字体"""
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun']
    plt.rcParams['axes.unicode_minus'] = False


def task1_data_analysis():
    """任务一：数据读取与描述性分析"""
    print("任务一：数据读取与描述性分析")
    print("-" * 40)

    try:
        df = pd.read_excel('比亚迪后复权历史行情数据.xlsx', sheet_name='Sheet2')
        print("数据形状:", df.shape)
        print("\n数据前5行:")
        print(df.head())

        print("\n数据列名:")
        print(df.columns.tolist())

        # 对定量变量进行描述性分析
        quantitative_vars = ['开盘', '收盘', '最高', '最低', '成交量', '成交额', '振幅', '涨跌幅', '涨跌额', '换手率']
        print("\n定量变量描述性统计分析:")
        desc_stats = df[quantitative_vars].describe()
        print(desc_stats)

        # 保存描述性统计结果
        desc_stats.to_csv('描述性统计分析结果.csv', encoding='utf-8-sig')
        print("\n描述性统计分析结果已保存到 '描述性统计分析结果.csv'")

        return df, quantitative_vars

    except Exception as e:
        print(f"数据读取时出错: {e}")
        return None, None


def task2_correlation_analysis(df, quantitative_vars):
    """任务二：相关系数分析与热力图"""
    print("\n" + "=" * 60)
    print("任务二：相关系数分析与热力图")
    print("-" * 40)

    try:
        correlation_matrix = df[quantitative_vars].corr()

        print("变量间相关系数矩阵:")
        print(correlation_matrix.round(3))

        # 绘制相关系数热力图
        plt.figure(figsize=(12, 8))
        sns.heatmap(correlation_matrix,
                    annot=True,
                    cmap='coolwarm',
                    center=0,
                    fmt='.3f',
                    square=True,
                    cbar_kws={"shrink": .8})
        plt.title('比亚迪股票变量相关系数热力图', fontsize=16, fontweight='bold')
        plt.tight_layout()
        plt.savefig('相关系数热力图.png', dpi=300, bbox_inches='tight')
        plt.close()
        print("相关系数热力图已保存为 '相关系数热力图.png'")

        # 输出强相关性分析
        print("\n强相关性分析 (|相关系数| > 0.8):")
        strong_corr = []
        for i in range(len(correlation_matrix.columns)):
            for j in range(i + 1, len(correlation_matrix.columns)):
                corr_val = abs(correlation_matrix.iloc[i, j])
                if corr_val > 0.8:
                    strong_corr.append((
                        correlation_matrix.columns[i],
                        correlation_matrix.columns[j],
                        correlation_matrix.iloc[i, j]
                    ))

        for var1, var2, corr in strong_corr:
            print(f"{var1} 与 {var2}: {corr:.3f}")

    except Exception as e:
        print(f"相关系数分析时出错: {e}")


def task3_price_trend(df):
    """任务三：2023年全年收盘价时序图"""
    print("\n" + "=" * 60)
    print("任务三：2023年全年收盘价时序图")
    print("-" * 40)

    try:
        # 确保日期列为datetime类型
        df['日期'] = pd.to_datetime(df['日期'])

        plt.figure(figsize=(14, 7))
        plt.plot(df['日期'], df['收盘'], linewidth=2, color='#2E86AB', label='收盘价')

        # 标记关键点位
        max_price = df['收盘'].max()
        min_price = df['收盘'].min()
        max_date = df.loc[df['收盘'].idxmax(), '日期']
        min_date = df.loc[df['收盘'].idxmin(), '日期']

        plt.scatter(max_date, max_price, color='red', s=100, zorder=5, label=f'最高点: {max_price:.2f}')
        plt.scatter(min_date, min_price, color='green', s=100, zorder=5, label=f'最低点: {min_price:.2f}')

        plt.title('比亚迪2023年全年收盘价时序图', fontsize=16, fontweight='bold')
        plt.xlabel('日期', fontsize=12)
        plt.ylabel('收盘价（元）', fontsize=12)
        plt.grid(True, alpha=0.3)
        plt.legend()

        # 设置x轴日期格式
        plt.gca().xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m'))
        plt.gca().xaxis.set_major_locator(plt.matplotlib.dates.MonthLocator())
        plt.gcf().autofmt_xdate()

        plt.tight_layout()
        plt.savefig('2023年收盘价时序图.png', dpi=300, bbox_inches='tight')
        plt.close()
        print("2023年收盘价时序图已保存为 '2023年收盘价时序图.png'")

        # 输出关键统计信息
        print(f"\n2023年收盘价关键统计:")
        print(f"最高收盘价: {max_price:.2f}元 (日期: {max_date.strftime('%Y-%m-%d')})")
        print(f"最低收盘价: {min_price:.2f}元 (日期: {min_date.strftime('%Y-%m-%d')})")
        annual_return = (df['收盘'].iloc[-1] - df['收盘'].iloc[0]) / df['收盘'].iloc[0] * 100
        print(f"年度涨跌幅: {annual_return:.2f}%")

    except Exception as e:
        print(f"绘制时序图时出错: {e}")


def task4_kline_analysis(df):
    """任务四：2023年4月-6月K线图绘制与分析"""
    print("\n" + "=" * 60)
    print("任务四：2023年4月-6月K线图绘制与分析")
    print("-" * 40)

    try:
        # 使用matplotlib绘制简易K线图
        fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), gridspec_kw={'height_ratios': [3, 1]})

        # 筛选时间段
        start_date = '2023-04-01'
        end_date = '2023-06-30'
        mask = (df['日期'] >= start_date) & (df['日期'] <= end_date)
        df_period = df[mask].copy()

        if len(df_period) > 0:
            # 绘制价格走势
            ax1.plot(df_period['日期'], df_period['收盘'], label='收盘价', color='blue', linewidth=2, marker='o', markersize=3)
            ax1.plot(df_period['日期'], df_period['开盘'], label='开盘价', color='red', linewidth=1, linestyle='--',
                     marker='s', markersize=2)
            ax1.fill_between(df_period['日期'], df_period['最低'], df_period['最高'], alpha=0.2, color='gray', label='价格区间')

            # 标记关键点
            period_max = df_period['最高'].max()
            period_min = df_period['最低'].min()
            period_max_date = df_period.loc[df_period['最高'].idxmax(), '日期']
            period_min_date = df_period.loc[df_period['最低'].idxmin(), '日期']

            ax1.scatter(period_max_date, period_max, color='darkred', s=80, zorder=5)
            ax1.scatter(period_min_date, period_min, color='darkgreen', s=80, zorder=5)

            ax1.set_title(f'比亚迪股票价格走势 ({start_date} 至 {end_date})', fontsize=16, fontweight='bold')
            ax1.set_ylabel('价格（元）')
            ax1.legend()
            ax1.grid(True, alpha=0.3)

            # 绘制成交量
            colors = ['green' if close >= open else 'red' for close, open in zip(df_period['收盘'], df_period['开盘'])]
            ax2.bar(df_period['日期'], df_period['成交量'], color=colors, alpha=0.7, label='成交量')
            ax2.set_ylabel('成交量')
            ax2.legend()
            ax2.grid(True, alpha=0.3)

            # 设置x轴日期格式
            ax1.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%m-%d'))
            ax2.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%m-%d'))
            plt.gcf().autofmt_xdate()

            plt.tight_layout()
            plt.savefig('2023年4-6月价格走势图.png', dpi=300, bbox_inches='tight')
            plt.close()
            print("2023年4-6月价格走势图已保存为 '2023年4-6月价格走势图.png'")

            # K线图分析
            print("\n" + "=" * 50)
            print("2023年4月-6月比亚迪股票分析报告")
            print("=" * 50)

            start_price = df_period['收盘'].iloc[0]
            end_price = df_period['收盘'].iloc[-1]
            period_return = (end_price - start_price) / start_price * 100

            print(f"期初价格 (4月): {start_price:.2f}元")
            print(f"期末价格 (6月): {end_price:.2f}元")
            print(f"期间收益率: {period_return:.2f}%")
            print(f"最高价: {df_period['最高'].max():.2f}元")
            print(f"最低价: {df_period['最低'].min():.2f}元")
            print(f"价格波动范围: {df_period['最高'].max() - df_period['最低'].min():.2f}元")
            print(f"平均成交量: {df_period['成交量'].mean():,.0f}手")

            # 计算上涨和下跌天数
            up_days = (df_period['涨跌幅'] > 0).sum()
            down_days = (df_period['涨跌幅'] < 0).sum()
            flat_days = (df_period['涨跌幅'] == 0).sum()

            print(f"\n交易天数统计:")
            print(f"上涨天数: {up_days}天")
            print(f"下跌天数: {down_days}天")
            print(f"平盘天数: {flat_days}天")

            print("\n技术分析要点:")
            if period_return > 5:
                print("• 趋势: 强势上涨趋势")
            elif period_return > 0:
                print("• 趋势: 温和上涨趋势")
            elif period_return > -5:
                print("• 趋势: 震荡整理")
            else:
                print("• 趋势: 下跌趋势")

            print("• 建议结合成交量观察价格变动的可靠性")
            print("• 关注支撑位和阻力位的突破情况")

        else:
            print("指定时间段内无数据")

    except Exception as e:
        print(f"绘制K线图时出错: {e}")


def main():
    """主函数"""
    print("开始执行比亚迪股票价格走势分析与可视化...")
    print("=" * 60)

    # 设置中文字体
    setup_chinese_font()

    # 执行任务一
    df, quantitative_vars = task1_data_analysis()

    if df is not None:
        # 执行任务二
        task2_correlation_analysis(df, quantitative_vars)

        # 执行任务三
        task3_price_trend(df)

        # 执行任务四
        task4_kline_analysis(df)

    print("\n" + "=" * 60)
    print("分析完成！所有结果已保存为文件。")
    print("生成的文件清单:")
    print("1. 描述性统计分析结果.csv - 定量变量的统计描述")
    print("2. 相关系数热力图.png - 变量间相关性可视化")
    print("3. 2023年收盘价时序图.png - 全年价格走势")
    print("4. 2023年4-6月价格走势图.png - 指定时间段详细分析")
    print("\n所有分析已完成，请查看生成的文件。")


if __name__ == "__main__":
    main()